package com.uinnova.product.eam.service.impl;

import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.cj.BaseEntity;
import com.uinnova.product.eam.base.exception.ServerException;
import com.uinnova.product.eam.base.model.BaseQueryDiagramDto;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.*;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.feign.workable.entity.TaskResponse;
import com.uinnova.product.eam.model.DiagramBo;
import com.uinnova.product.eam.model.EamArtifactVo;
import com.uinnova.product.eam.model.EamCategoryCdt;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.cj.domain.PlanDesignShareRecord;
import com.uinnova.product.eam.model.cj.enums.PlanStatusEnum;
import com.uinnova.product.eam.model.cj.vo.DiagramPlanVO;
import com.uinnova.product.eam.model.cj.vo.PlanDesignInstanceVO;
import com.uinnova.product.eam.model.cj.vo.PlanDesignResponseVO;
import com.uinnova.product.eam.model.cj.vo.PlanHistoryVersionVo;
import com.uinnova.product.eam.model.constants.Constants;
import com.uinnova.product.eam.model.constants.DiagramConstant;
import com.uinnova.product.eam.model.diagram.SpaceResourceResultInfo;
import com.uinnova.product.eam.model.dto.EamCategoryDTO;
import com.uinnova.product.eam.model.dto.EamResourceDetail;
import com.uinnova.product.eam.model.enums.AssetType;
import com.uinnova.product.eam.model.enums.CategoryTypeEnum;
import com.uinnova.product.eam.model.enums.ModelTypeEnum;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.IAttentionSvc;
import com.uinnova.product.eam.service.asset.IRecentlyViewSvc;
import com.uinnova.product.eam.service.cj.service.FlowableService;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.cj.service.ShareService;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.diagram.DiagramShareRecord;
import com.uinnova.project.base.diagram.comm.diagram.ESDiagramShareRecordResult;
import com.uinnova.project.base.diagram.comm.diagram.EamDiagramQuery;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.base.diagram.comm.model.ESDiagramDTO;
import com.uinnova.project.base.diagram.comm.model.ESDiagramInfoDTO;
import com.uinnova.project.base.diagram.comm.model.ESSimpleDiagramDTO;
import com.uinnova.project.db.eam.ESDiagramDao;
import com.uinnova.project.service.eam.ESShareDiagramSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysRole;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.business.UserInfo;
import com.uino.bean.permission.query.CSysUser;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * eam视图相关接口
 */
@Slf4j
@Service
public class EamDiagramSvcImplV2 implements IEamDiagramSvcV2 {
    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    private IVersionTagSvc versionTagSvc;
    @Resource
    private ESDiagramApiClient diagramApiClient;
    @Resource
    private PlanDesignInstanceService planService;
    @Value("${http.resource.space}")
    private String httpResourceUrl;
    @Resource
    private ICISwitchSvc ciSwitchSvc;
    @Resource
    private IUserApiSvc userApiSvc;
    @Resource
    private IEamArtifactSvc artifactSvc;
    @Resource
    private ESShareDiagramSvc shareDiagramSvc;
    @Resource
    private FlowableService flowableService;
    @Resource
    private EamModelSvc modelSvc;
    @Resource
    private IAttentionSvc attentionSvc;
    @Resource
    private ShareService planShareService;
    @Resource
    private IBmMultiModelHierarchySvc modelHierarchySvc;
    @Resource
    private EamDiagramRelationSysService diagramRelationSysService;
    @Autowired
    private ESDiagramDao esDiagramDao;
    @Autowired
    private IRecentlyViewSvc recentlyViewSvc;

    @Override
    public SpaceResourceResultInfo getDiagramByDirId(BaseQueryDiagramDto dto) {
        UserInfo user = userApiSvc.getUserInfoByLoginCode(SysUtil.getCurrentUserInfo().getLoginCode());
        List<SysRole> adminRoles = user.getRoles().stream().filter(role -> "admin".equals(role.getRoleName())).collect(Collectors.toList());
        boolean isAdmin = !CollectionUtils.isEmpty(adminRoles);
        //处理下模型版本切换时dto.getId为版本标签id，这里需要查下对应的目录并将参数转一下
        if (dto.isHistoryFlag() && LibType.DESIGN.equals(dto.getLibType())) {
            EamVersionDir versionDir = versionTagSvc.getByDirId(dto.getId());
            dto.setVersionId(dto.getId());
            dto.setId(versionDir.getDirId());
        }
        //当前目录
        EamCategory category = categorySvc.getById(dto.getId(), dto.getLibType());
        if (dto.getId() != 0L && category == null) {
            throw new BinaryException("目录已被删除，请刷新页面");
        }
        SpaceResourceResultInfo result = new SpaceResourceResultInfo();

        EamCategoryDTO categoryDTO = new EamCategoryDTO();
        if(LibType.DESIGN.equals(dto.getLibType())){
            categoryDTO = categorySvc.getFolderPermission(dto.getId(), user.getLoginCode());
            if (categoryDTO.getType() != CategoryTypeEnum.ROOT.val()
                    && categoryDTO.getFolderPermissionManager() == null) {
                throw new BinaryException("暂无权限");
            }
            result.setCategory(categoryDTO);
        }
        //子目录
        List<EamCategoryDTO> childList = this.queryChildrenDirs(dto, category);
        List<EamCategoryDTO> childrenDirs = new ArrayList<>();
        //文件夹
        if (this.showFolder(isAdmin, dto.getLibType(), categoryDTO)) {
            List<EamCategoryDTO> folders = childList.stream()
                    .filter(folder -> folder.getType() != null)
                    .filter(folder -> !folder.getId().equals(dto.getId()))
                    .filter(folder -> !folder.getType().equals(CategoryTypeEnum.MODEL.val()))
                    .filter(folder -> !folder.getType().equals(CategoryTypeEnum.MODEL_ROOT.val()))
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(folders)) {
                childrenDirs.addAll(folders);
            }
        }
        //模型
        if (this.showModel(isAdmin, dto.getLibType(), categoryDTO)) {
            List<EamCategoryDTO> models = childList.stream()
                    .filter(folder -> folder.getType() != null)
                    .filter(folder -> folder.getType().equals(CategoryTypeEnum.MODEL.val())
                            || folder.getType().equals(CategoryTypeEnum.MODEL_ROOT.val()))
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(models)) {
                childrenDirs.addAll(models);
            }
        }
        result.setChildrenDirs(childrenDirs);
        if (this.showFile(isAdmin, dto.getLibType(), categoryDTO)) {
            //有权限查看的目录列表
            List<EamCategoryDTO> readCategories = categorySvc.queryChildsWithFileReadPemissonByParentIds(Arrays.asList(dto.getId()), dto.getLibType());
            if (LibType.DESIGN.equals(dto.getLibType()) && categoryDTO.getType() == CategoryTypeEnum.ROOT.val()) {
                //加入根目录
                readCategories.add(categoryDTO);
            }
            //资产库数据查当人关注
            Set<Long> attentionSet = this.queryAttention(dto);

            //查询视图
            List<DiagramPlanVO> diagramInfo = queryDiagramInfo(dto, readCategories, user.getLoginCode(), attentionSet, category);
            //查询方案
            List<DiagramPlanVO> planInfo = queryPlanInfo(dto, dto.getId(), user.getLoginCode(), attentionSet, readCategories);
            diagramInfo.addAll(planInfo);
            //判断是否数据模型目录
            result.setDataModelFlag(checkDataModel(dto, category));
            // 按时间降序排序
            diagramInfo.sort((DiagramPlanVO o1, DiagramPlanVO o2) -> (int) (o2.getModifyTime() - o1.getModifyTime()));
            //如果是模型目录，将模型视图放在第一个
            if(diagramInfo.size()>0 && category != null && !BinaryUtils.isEmpty(category.getDiagramId())){
                int index = 0;
                for (int i = 0; i < diagramInfo.size(); i++) {
                    ESDiagram diagram = diagramInfo.get(i).getDiagram();
                    if(diagram != null && diagram.getDEnergy().equals(category.getDiagramId())){
                        index = i;
                    }
                }
                Collections.swap(diagramInfo, index, 0);
            }
            result.setDiagramPlanList(diagramInfo);
        }
        return result;
    }

    /**
     * 判断是否数据模型目录
     */
    private boolean checkDataModel(BaseQueryDiagramDto dto, EamCategory category) {
        Long modelId;
        if(dto.isHistoryFlag()){
            EamVersionDir versionDir = versionTagSvc.getByDirId(dto.getId());
            if(versionDir == null){
                return false;
            }
            EamVersionTag tag = versionTagSvc.getByTagId(versionDir.getTagId());
            if(tag == null){
                return false;
            }
            modelId = tag.getBranchId();
        }else{
            if(category == null || (category.getType()!=CategoryTypeEnum.MODEL.val() && category.getType()!=CategoryTypeEnum.MODEL_ROOT.val())){
                return false;
            }
            modelId = category.getModelId();
        }
        EamMultiModelHierarchy model = modelHierarchySvc.getModelById(modelId);
        return model != null && model.getModelType() != null && model.getModelType() == ModelTypeEnum.DATA.val();
    }

    private Set<Long> queryAttention(BaseQueryDiagramDto dto) {
        Set<Long> attentionSet = new HashSet<>();
        List<EamAttention> attentions = attentionSvc.findCurrentUserAttentionList();
        if (!CollectionUtils.isEmpty(attentions)) {
            attentionSet = attentions.stream().map(EamAttention::getAttentionId).collect(Collectors.toSet());
        }
        return attentionSet;
    }

    private List<EamCategoryDTO> queryChildrenDirs(BaseQueryDiagramDto dto, EamCategory category) {
        List<EamCategoryDTO> childList = new ArrayList<>();
        if(dto.getId().equals(0L) || (category!=null && CategoryTypeEnum.MODEL.val() != category.getType() && CategoryTypeEnum.MODEL_ROOT.val() != category.getType())){
            if(dto.getId().equals(0L) && !BinaryUtils.isEmpty(dto.getLike())){
                List<EamCategory> categoryList = categorySvc.queryPrivateList(dto.getId(), dto.getLike());
                childList = EamUtil.copy(categoryList, EamCategoryDTO.class);
            }else{
                childList = categorySvc.queryListByParentId(dto.getId(), dto.getLike(), true, dto.getLibType());
                //过滤断层数据
                if (LibType.DESIGN.equals(dto.getLibType())) {
                    childList = categorySvc.filterIfParentNotExistDTO(Arrays.asList(dto.getId()), childList);
                }
            }
            childList = childList.stream().filter(each -> each.getType() != CategoryTypeEnum.MODEL.val()).collect(Collectors.toList());
            for (EamCategoryDTO each : childList) {
                if(CategoryTypeEnum.MODEL_ROOT.val() == each.getType()){
                    each.setAssetType(AssetType.MODEL);
                }else{
                    each.setAssetType(AssetType.FOLDER);
                }
            }
        }
        return childList;
    }

    private List<DiagramPlanVO> queryPlanInfo(BaseQueryDiagramDto dto, Long id, String loginCode, Set<Long> attentionSet, List<EamCategoryDTO> readCategories){
        List<DiagramPlanVO> result = new ArrayList<>();
        List<PlanDesignInstance> planDesignList;
        List<Long> dirIds = Collections.singletonList(id);
        if(!BinaryUtils.isEmpty(dto.getLike())){
            dirIds = readCategories.stream().map(EamCategoryDTO::getId).distinct().collect(Collectors.toList());
            if(dto.getId().equals(0L)){
                dirIds.add(0L);
            }
        }
        Map<Long, List<PlanDesignShareRecord>> shareMap = Collections.emptyMap();
        if (LibType.PRIVATE.equals(dto.getLibType())) {
            planDesignList = planService.findPlanDesignList(null, id, dto.getLike(), loginCode);
            if (!CollectionUtils.isEmpty(planDesignList)) {
                List<Long> planIds = planDesignList.stream().map(PlanDesignInstance::getId).collect(Collectors.toList());
                shareMap = planShareService.selectByPlanIds(planIds);
            }

        }else{
            planDesignList = planService.getPublishedPlan(dirIds, dto.getLike());
        }
        if(CollectionUtils.isEmpty(planDesignList)){
            return result;
        }
        Set<String> loginCodeSet = new HashSet<>();
        for (PlanDesignInstance plan : planDesignList) {
            if (!StringUtils.isEmpty(plan.getCreatorCode())) {
                loginCodeSet.add(plan.getCreatorCode());
            }
            if (!StringUtils.isEmpty(plan.getModifierCode())) {
                loginCodeSet.add(plan.getModifierCode());
            }
        }
        Map<String, SysUser> userMap = queryUserMap(loginCodeSet);
        for (PlanDesignInstance plan : planDesignList) {
            DiagramPlanVO diagramPlan = new DiagramPlanVO();
            diagramPlan.setCreator(userMap.get(plan.getCreatorCode()));
            PlanDesignResponseVO responseVO = new PlanDesignResponseVO();
            BeanUtils.copyProperties(plan, responseVO);
            if (plan.isProcessApproval()) {
                TaskResponse task = flowableService.getCurrentTaskAssignees(String.valueOf(plan.getId()));
                if (task != null && !BinaryUtils.isEmpty(task.getSubmitter()) && !BinaryUtils.isEmpty(task.getCurrentAssignees())) {
                    if (!Objects.equals(loginCode, task.getSubmitter()) && task.getCurrentAssignees().contains(loginCode)) {
                        responseVO.setStatus(PlanStatusEnum.under_approver.name());
                    } else if (Objects.equals(loginCode, task.getSubmitter()) && task.getCurrentAssignees().contains(loginCode)) {
                        responseVO.setStatus(PlanStatusEnum.under_submitter.name());
                    } else if (Objects.equals(loginCode, task.getSubmitter()) && !task.getCurrentAssignees().contains(loginCode)) {
                        responseVO.setStatus(PlanStatusEnum.under_approver.name());
                    }
                }
            }
            if (userMap.get(plan.getCreatorCode()) != null) {
                responseVO.setCreatorName(userMap.get(plan.getCreatorCode()).getUserName());
            }
            if (userMap.get(plan.getModifierCode()) != null) {
                responseVO.setModifierName(userMap.get(plan.getModifierCode()).getUserName());
            }
            diagramPlan.setPlanDesignInstance(responseVO);
            diagramPlan.setAssetType(AssetType.SCHEME);
            diagramPlan.setModifyTime(plan.getModifyTime());
            if (attentionSet.contains(plan.getId())) {
                diagramPlan.setIsAttention(DiagramConstant.IS_ATTENTION);
            }
            if (CollectionUtils.isEmpty(shareMap.get(plan.getId()))) {
                diagramPlan.setShare(false);
            } else {
                diagramPlan.setShare(true);
            }
            // 设置方案状态
            if (!BinaryUtils.isEmpty(plan.getStatus())) {
                if ("draft".equals(plan.getStatus())) {
                    if (plan.isProcessApproval()) {
                        diagramPlan.setReleaseStatus(2);
                    } else {
                        diagramPlan.setReleaseStatus(0);
                    }
                } else if ("approve".equals(plan.getStatus())) {
                    diagramPlan.setReleaseStatus(2);
                } else if ("approve_edit".equals(plan.getStatus())) {
                    diagramPlan.setReleaseStatus(3);
                } else if ("published".equals(plan.getStatus())) {
                    diagramPlan.setReleaseStatus(1);
                }
            }
            result.add(diagramPlan);
        }
        return result;
    }

    private List<DiagramPlanVO> queryDiagramInfo(BaseQueryDiagramDto dto, List<EamCategoryDTO> readCategories, String loginCode, Set<Long> attentionSet, EamCategory category){
        List<DiagramPlanVO> result = new ArrayList<>();
        List<Long> dirIds = Lists.newArrayList(dto.getId());
        List<EamVersionDiagram> diagramHistoryList = new ArrayList<>();
        BoolQueryBuilder diagramQuery = QueryBuilders.boolQuery();
        if(dto.isHistoryFlag()){
            //历史版本目录
            EamVersionDir versionDir = versionTagSvc.getByDirId(dto.getVersionId());
            if(BinaryUtils.isEmpty(versionDir)){
                throw new ServerException("未获取到当前历史版本目录信息,请联系管理员!");
            }
            if (!BinaryUtils.isEmpty(dto.getLike())) {
                List<EamVersionDir> dirList = versionTagSvc.getVersionDirByTagId(versionDir.getTagId());
                dirIds = dirList.stream().map(EamVersionDir::getDirId).collect(Collectors.toList());
                diagramHistoryList = dirList.stream().map(EamVersionDir::getDiagramList).flatMap(Collection::stream).collect(Collectors.toList());
            }else{
                dirIds = Lists.newArrayList(versionDir.getDirId());
                diagramHistoryList = versionDir.getDiagramList();
            }
        } else {
            diagramQuery.must(QueryBuilders.termQuery("dataStatus", 1));
            diagramQuery.must(QueryBuilders.termQuery("status", 1));
            diagramQuery.must(QueryBuilders.termQuery("historyVersionFlag", 1));
            //TODO 模糊搜索时得获取下所有目录 dirIds
        }
        if (BinaryUtils.isEmpty(dto.getLike())){
            diagramQuery.must(QueryBuilders.termsQuery("dirId", dirIds));
        }else{
            List<Long> childIds = readCategories.stream().map(EamCategoryDTO::getId).distinct().collect(Collectors.toList());
            if(dto.getId().equals(0L)){
                childIds.add(0L);
            }
            diagramQuery.must(QueryBuilders.termsQuery("dirId", childIds));
            diagramQuery.must(QueryBuilders.wildcardQuery("name.keyword", "*" + dto.getLike().trim() + "*"));
        }
        if(LibType.PRIVATE.equals(dto.getLibType())){
            diagramQuery.must(QueryBuilders.termQuery("ownerCode.keyword", loginCode));
            diagramQuery.must(QueryBuilders.termQuery("isOpen", 0));
        }else{
            diagramQuery.must(QueryBuilders.termQuery("isOpen", 1));
        }
        // 视图类型 1:普通视图 3: 公共模板 4:个人模板
        diagramQuery.must(QueryBuilders.termsQuery("diagramType", Lists.newArrayList(1,2,3,4)));
        Page<ESDiagram> diagramPage = diagramApiClient.selectListByQuery(dto.getPageNum(), dto.getPageSize(), diagramQuery);
        if(BinaryUtils.isEmpty(diagramPage.getData())){
            return result;
        }
        // 判断当前目录是否为审批
        Boolean isApprove = true;
        Boolean modelDiagram = false;
        if (!BinaryUtils.isEmpty(category) && (category.getType() == 4 || category.getType() == 5)) {
            isApprove = false;
            modelDiagram = true;
        }

        List<String> energyIds = new ArrayList<>();
        Set<Long> artifactIds = new HashSet<>();
        Set<String> ownerCodes = new HashSet<>();
        List<Long> diagramIds = new ArrayList<>();
        Map<String, Integer> versionMap = new HashMap<>(16);
        if(dto.isHistoryFlag()){
            versionMap = diagramHistoryList.stream().collect(Collectors.toMap(EamVersionDiagram::getDiagramId, EamVersionDiagram::getVersion, (k1,k2)->k2));
        }
        List<ESDiagram> data = new ArrayList<>();
        for (ESDiagram each : diagramPage.getData()) {
            if(dto.isHistoryFlag()){
                if(BinaryUtils.isEmpty(each.getReleaseDiagramId())){
                    continue;
                }
                Integer version = versionMap.get(each.getReleaseDiagramId());
                if(BinaryUtils.isEmpty(version) || !version.equals(each.getReleaseVersion())){
                    continue;
                }
            }
            data.add(each);
            energyIds.add(each.getDEnergy());
            diagramIds.add(each.getId());
            if(!BinaryUtils.isEmpty(each.getViewType())){
                artifactIds.add(Long.parseLong(each.getViewType()));
            }
            if(!BinaryUtils.isEmpty(each.getOwnerCode())){
                ownerCodes.add(each.getOwnerCode());
            }
        }
        if(BinaryUtils.isEmpty(data)){
            return result;
        }
        //TODO 这里逻辑先保留，后面看怎么优化(不一定需要)
        List<EamCategory> categoryList = categorySvc.queryByDiagramId(energyIds, loginCode, dto.getLibType());
        Map<String, EamCategory> diagramDirMap = categoryList.stream().filter(each -> !BinaryUtils.isEmpty(each.getDiagramId())).
                collect(Collectors.toMap(EamCategory::getDiagramId, each -> each, (k1, k2) -> k1));
        Map<String, String> dictMap = new HashMap<>(16);
        for (String diagramId : energyIds) {
            EamCategory each = diagramDirMap.get(diagramId);
            if (BinaryUtils.isEmpty(each) || each.getParentId() == 0L || BinaryUtils.isEmpty(each.getCiCode())) {
                continue;
            }
            dictMap.put(diagramId, each.getCiCode());
        }

        //根据制品id制品，再与视图一一匹配。
        List<EamArtifact> eamArtifacts = artifactSvc.queryArtifactListByIds(Lists.newArrayList(artifactIds), 1);
        Map<Long, EamArtifact> artifactMap = eamArtifacts.stream().collect(Collectors.toMap(EamArtifact::getId, each -> each, (k1, k2) -> k1));
        //查询视图的分享记录
        Map<Long, List<ESDiagramShareRecordResult>> shareRecordMap = new HashMap<>(16);
        if (LibType.PRIVATE.equals(dto.getLibType())) {
            //TODO 这里可以优化，做个简单查询
            shareRecordMap = shareDiagramSvc.queryDiagramShareRecords(diagramIds.toArray(new Long[0]), false);
        }
        Map<String, Long> ciMap = new HashMap<>(16);
        if (!dictMap.isEmpty()) {
            List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(Lists.newArrayList(dictMap.values()), loginCode, dto.getLibType());
            ciMap = ciList.stream().collect(Collectors.toMap(ESCIInfo::getCiCode, ESCIInfo::getId, (k1, k2) -> k1));
        }
        Map<String, SysUser> userMap = queryUserMap(ownerCodes);
        for (ESDiagram each : data) {
            DiagramPlanVO diagram = new DiagramPlanVO();
            diagram.setAssetType(AssetType.DIAGRAM);
            diagram.setDiagram(each);
            diagram.setCreator(userMap.get(each.getOwnerCode()));
            diagram.setShare(shareRecordMap.get(each.getId())!=null);
            if(BinaryUtils.isEmpty(each.getReleaseDiagramId())){
               diagram.setReleaseStatus(0);
            }else{
                diagram.setReleaseStatus(1);
            }
            if (!BinaryUtils.isEmpty(each.getFlowStatus())) {
                if (!each.getFlowStatus().equals(0)) {
                    diagram.setReleaseStatus(2);
                }
            }
            if (!BinaryUtils.isEmpty(each.getViewType())) {
                //查询视图中绑定的制品类型分类
                EamArtifact artifact = artifactMap.get(Long.valueOf(each.getViewType()));
                if(!BinaryUtils.isEmpty(artifact)){
                    diagram.setArtifactType(artifact.getTypeClassification());
                    diagram.getDiagram().setDirType(artifact.getTypeClassification());
                }
                if(dictMap.containsKey(each.getDEnergy())){
                    String ciCode = dictMap.get(each.getDEnergy());
                    if(ciCode != null && ciMap.get(ciCode) != null){
                        diagram.setAttachCiId(ciMap.get(ciCode));
                    }
                    diagram.setAttachCiCode(ciCode);
                }
            }
            diagram.setModifyTime(each.getModifyTime());
            if (attentionSet.contains(each.getId())) {
                diagram.setIsAttention(DiagramConstant.IS_ATTENTION);
            }
            diagram.setModelDiagram(modelDiagram);
            diagram.setIsApprove(isApprove);
            result.add(diagram);
        }
        return result;
    }

    @Override
    public Integer removeCiInDiagram(EamCategoryCdt cdt) {
        ESDiagram diagram = diagramApiClient.getEsDiagram(cdt.getDiagramId(), 0);
        EamCategory category = categorySvc.getById(diagram.getDirId(), LibType.PRIVATE);
        List<String> ciCodeList = new ArrayList<>(cdt.getCiCodes());
        if(category != null && category.getType() == CategoryTypeEnum.MODEL.val()){
            if(ciCodeList.contains(category.getCiCode())){
                throw new BinaryException("继承节点不可删除");
            }
            if(cdt.getDelType() == 0 && diagram.getDEnergy().equals(category.getDiagramId())){
                //自动成图调用删除,过滤掉有视图的目录
                List<EamCategory> childList = categorySvc.selectByParentId(category.getId(), category.getOwnerCode(), LibType.PRIVATE);
                if(CollectionUtils.isEmpty(childList)){
                    return 1;
                }
                ciCodeList = childList.stream().map(EamCategory::getCiCode).filter(each -> !cdt.getCiCodes().contains(each)).collect(Collectors.toList());
            }
        }
        if (cdt.getDelType() == 2) {
            //删除节点数据
            List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(ciCodeList, diagram.getOwnerCode(), LibType.PRIVATE);
            if (!BinaryUtils.isEmpty(ciList)) {
                List<Long> ids = ciList.stream().map(ESCIInfo::getId).collect(Collectors.toList());
                ciSwitchSvc.removeByIds(ids, null, LibType.PRIVATE);
            }
        }
        if(category == null || category.getType() != CategoryTypeEnum.MODEL.val() || !diagram.getDEnergy().equals(category.getDiagramId())){
            return 1;
        }
        List<EamCategory> categoryList = categorySvc.selectListByCiCodes(category.getModelId(), ciCodeList, diagram.getOwnerCode(), LibType.PRIVATE);
        if(CollectionUtils.isEmpty(categoryList)){
            return 1;
        }
        List<Long> dirIds = categoryList.stream().map(EamCategory::getId).distinct().collect(Collectors.toList());
        modelSvc.deleteCategory(dirIds, Constants.DELETE_PHYSICAL, diagram.getOwnerCode(), LibType.PRIVATE);
        return 1;
    }

    @Override
    public EamResourceDetail detail(EamCategoryCdt cdt) {
        EamResourceDetail result = new EamResourceDetail();
        if(cdt.getDirId()==null && cdt.getDiagramId()==null && cdt.getPlanId()==null){
            return result;
        }
        String ownerCode;
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        int isRelease = 0;
        if (LibType.DESIGN.equals(cdt.getLibType())) {
            isRelease = 1;
            loginCode = null;
        }
        if(!BinaryUtils.isEmpty(cdt.getDirId())){
            //文件夹详情
            EamCategory category = categorySvc.getById(cdt.getDirId(), cdt.getLibType());
            result.setAssetType(AssetType.FOLDER);
            result.setName(category.getDirName());
            List<EamCategory> childList = categorySvc.queryByRootId(cdt.getDirId(), 1, loginCode, cdt.getLibType());
            List<Long> dirIdList = childList.stream().map(EamCategory::getId).collect(Collectors.toList());
            List<ESDiagram> esDiagrams = diagramApiClient.selectByDirIds(dirIdList, Lists.newArrayList(1), null, Lists.newArrayList(isRelease));
            result.setArtifactNum(esDiagrams.size());
            ownerCode = category.getOwnerCode();
            result.setCreateTime(category.getCreateTime());
            result.setModifyTime(category.getModifyTime());
        }else if(!BinaryUtils.isEmpty(cdt.getDiagramId())){
            //视图详情
            ESDiagram diagram = diagramApiClient.getEsDiagram(cdt.getDiagramId(), LibType.PRIVATE.equals(cdt.getLibType()) ? 0 : 1);
            if(diagram == null){
                return result;
            }
            result.setAssetType(AssetType.DIAGRAM);
            result.setName(diagram.getName());
            String icon = diagram.getIcon1();
            result.setIcon(icon);
            if (icon != null && !icon.startsWith(this.httpResourceUrl)) {
                result.setIcon(httpResourceUrl + icon);
            }
            if(LibType.PRIVATE.equals(cdt.getLibType())){
                List<DiagramShareRecord> shareRecords = shareDiagramSvc.getByDiagramId(cdt.getDiagramId());
                if(!CollectionUtils.isEmpty(shareRecords)){
                    result.setShare(true);
                }
            }
            if(!BinaryUtils.isEmpty(diagram.getViewType())){
                EamArtifactVo artifact = artifactSvc.queryArtifact(Long.parseLong(diagram.getViewType()));
                if(artifact != null){
                    result.setArtifactName(artifact.getArtifactName());
                }
            }
            long totalRows = planService.findDiagramPlanList(1, 1, cdt.getDiagramId(), isRelease).getTotalRows();
            result.setPlanNum((int) totalRows);
            //所在文件夹
            if(diagram.getDirId() == 0L){
                result.setDirName("我的空间");
            }else{
                EamCategory category = categorySvc.getById(diagram.getDirId(), cdt.getLibType());
                if(category != null){
                    result.setDirName(category.getDirName());
                }
            }
            ownerCode = diagram.getOwnerCode();
            result.setDiagramId(cdt.getDiagramId());
            result.setCreateTime(diagram.getCreateTime());
            result.setModifyTime(diagram.getModifyTime());
            // 关联资产名称
            EamDiagramRelationSys diagramRelation = diagramRelationSysService.getEamDiagramRelationSys(cdt.getDiagramId());
            if (!BinaryUtils.isEmpty(diagramRelation)) {
                List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(Collections.singletonList(diagramRelation.getEsSysId()), null, LibType.DESIGN);
                if (!CollectionUtils.isEmpty(ciList)) {
                    ESCIInfo ci = ciList.get(0);
                    String ciName = BinaryUtils.isEmpty(ci.getCiLabel()) || "[]".equals(ci.getCiLabel()) ? ci.getCiPrimaryKey() : ci.getCiLabel();
                    result.setCiName(ciName);
                }
            }
        }else{
            //方案详情
            PlanDesignInstanceVO plan = planService.getById(cdt.getPlanId());
            result.setAssetType(AssetType.SCHEME);
            result.setName(plan.getName());
            result.setPlanTemplateTypeId(plan.getTypeId());
            result.setSystemCiCodes(plan.getSystemCiCodes());
            result.setPlanBindClassId(plan.getDefaultSystemClassId());
            result.setPlanBindProject(plan.getPlanBindProject());
            result.setSystemNames(plan.getSystemNames());
            if(LibType.PRIVATE.equals(cdt.getLibType())){
                List<PlanDesignShareRecord> shareRecords = planShareService.getByPlanId(cdt.getPlanId());
                if(!CollectionUtils.isEmpty(shareRecords)){
                    result.setShare(true);
                }
            }
            ownerCode = plan.getCreatorCode();
            //所在文件夹
            Long dirId = cdt.getLibType().equals(LibType.PRIVATE) ? plan.getDirId() : plan.getAssetsDirId();
            if(dirId == 0L){
                result.setDirName("我的空间");
            }else{
                EamCategory category = categorySvc.getById(dirId, cdt.getLibType());
                if(category != null){
                    result.setDirName(category.getDirName());
                }
            }
            // 获取方案关联资产名称
            planService.findPlanHistoryVersionList(cdt.getPlanId());
            if (!CollectionUtils.isEmpty(plan.getCiCodeList())) {
                List<ESCIInfo> ciInfoList = ciSwitchSvc.getCiByCodes(plan.getCiCodeList(), null, LibType.DESIGN);
                List<String> ciLabelList = ciInfoList.stream().filter(esciInfo -> !BinaryUtils.isEmpty(esciInfo.getCiLabel()))
                        .map(esciInfo -> esciInfo.getCiLabel().replace("[", "").replace("]", "").replaceAll("\"", ""))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(ciLabelList)) {
                    result.setAssetName(StringUtils.join(ciLabelList, "-"));
                }
            }
            List<PlanHistoryVersionVo> versionList = planService.findPlanHistoryVersionList(cdt.getPlanId());
            if (!CollectionUtils.isEmpty(versionList)) {
                result.setNewestVersion(versionList.get(0).getVersion());
            }
            result.setRemark(plan.getExplain());
            result.setPlanType(plan.getTypeName());
            result.setPlanTemplate(plan.getTemplateName());
            result.setCreateTime(plan.getCreateTime());
            result.setModifyTime(plan.getModifyTime());
        }
        UserInfo userInfo = null;
        try {
            userInfo = userApiSvc.getUserInfoByLoginCode(ownerCode);
        } catch (Exception e){
            log.error("{}用户不存在", ownerCode);
        }
        String userName = userInfo == null ? ownerCode : userInfo.getUserName();
        result.setCreator(userName);
        return result;
    }

    @Override
    public Map<String, String> createDiagram(ESDiagramInfoDTO diagramDto) {
        //制品id不为空，处理dirType字段为制品类型
        if(!BinaryUtils.isEmpty(diagramDto.getViewType())){
            EamArtifactVo artifact = artifactSvc.queryArtifact(Long.parseLong(diagramDto.getViewType()));
            if(artifact != null){
                diagramDto.setDirType(artifact.getTypeClassification());
            }
        }else{
            diagramDto.setDirType(0);
        }
        Map<String, String> data = diagramApiClient.saveESDiagram(diagramDto);
        //维护最近查看、最近编辑记录
        addRecentView(data);
        return data;
    }

    private void addRecentView(Map<String, String> data) {
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        String diagramId = data.get("diagramId");
        if (StringUtils.isBlank(diagramId)) {
            return;
        }
        CEamRecentlyView ceamRecentlyView = new CEamRecentlyView();
        ceamRecentlyView.setUserId(SysUtil.getCurrentUserInfo().getId());
        ceamRecentlyView.setDiagramId(diagramId);
        ceamRecentlyView.setViewType(1);
        ceamRecentlyView.setViewArchitectureType(1);
        recentlyViewSvc.saveOrUpdateRecentlyView(ceamRecentlyView);
    }

    /**
     * 获取用户信息map
     * @param codes 用户code
     */
    private Map<String, SysUser> queryUserMap(Collection<String> codes) {
        CSysUser cSysUser = new CSysUser();
        cSysUser.setLoginCodes(codes.toArray(new String[0]));
        cSysUser.setSuperUserFlags(new Integer[]{0, 1});
        List<SysUser> userList = userApiSvc.getSysUserByCdt(cSysUser);
        Map<String, SysUser> userIdObjMap = new HashMap<>(userList.size());
        for (SysUser user : userList) {
            user.setLoginPasswd(null);
            String icon = user.getIcon();
            if (icon != null && !icon.startsWith(this.httpResourceUrl)) {
                user.setIcon(httpResourceUrl + icon);
            }
            userIdObjMap.put(user.getLoginCode(), user);
        }
        return userIdObjMap;
    }

    @Override
    public ESDiagramInfoDTO openNextDiagram(EamCategoryCdt params) {
        List<ESDiagram> esDiagrams = diagramApiClient.selectByIds(Collections.singletonList(params.getDiagramId()), null, null);
        if(BinaryUtils.isEmpty(esDiagrams) || esDiagrams.get(0).getDiagramSubType()!=4){
            return new ESDiagramInfoDTO();
        }
        LibType libType = LibType.PRIVATE;
        if(esDiagrams.get(0).getIsOpen() == 1){
            libType = LibType.DESIGN;
        }
        EamCategory category = categorySvc.getById(esDiagrams.get(0).getDirId(), libType);
        EamCategory next = categorySvc.getModelByCiCode(category.getModelId(), params.getCiCode(), category.getOwnerCode(), libType);
        if (next==null || BinaryUtils.isEmpty(next.getDiagramId())) {
            return new ESDiagramInfoDTO();
        }
        List<ESDiagramDTO> diagram = diagramApiClient.queryFullDiagramByIds(Collections.singletonList(next.getDiagramId()));
        if (BinaryUtils.isEmpty(diagram)) {
            return new ESDiagramInfoDTO();
        }
        ESDiagramDTO diagramDTO = diagram.get(0);
        String icon1 = diagramDTO.getDiagram().getIcon1();
        if (icon1 != null && !icon1.startsWith(httpResourceUrl)) {
            icon1 = httpResourceUrl + icon1;
            diagramDTO.getDiagram().setIcon1(icon1);
        }
        return diagramDTO.getDiagram();
    }

    private Boolean baseShow(Boolean isAdmin, LibType libType, Integer categoryType) {
        return isAdmin || LibType.PRIVATE.equals(libType)
                || categoryType.equals(CategoryTypeEnum.ROOT.val());
    }

    private Boolean showFolder(Boolean isAdmin, LibType libType, EamCategoryDTO dto) {
        return baseShow(isAdmin, libType, dto.getType())
                || (dto.getFolderPermissionManager().getFolderPermissions().getRead()
                && dto.getFolderPermissionManager().getFolderApplicationScope().getCurrentFolder());
    }

    private Boolean showFile(Boolean isAdmin, LibType libType, EamCategoryDTO dto) {
        return baseShow(isAdmin, libType, dto.getType())
                || (dto.getFolderPermissionManager().getFilePermissions().getRead()
                && dto.getFolderPermissionManager().getFolderApplicationScope().getCurrentFolder());
    }

    private Boolean showModel(Boolean isAdmin, LibType libType, EamCategoryDTO dto) {
        return baseShow(isAdmin, libType, dto.getType())
                || (dto.getFolderPermissionManager().getModelPermission().getRead()
                && dto.getFolderPermissionManager().getFolderApplicationScope().getCurrentFolder());
    }

    @Override
    public boolean checkDirExistData(List<Long> categoryIdList) {
        //当前目录
        Map<Long, List<EamCategory>> childrenDir = categorySvc.queryChildrenDirsByParentIds(categoryIdList, LibType.DESIGN);
        if (!CollectionUtils.isEmpty(childrenDir)) {
            return true;
        }
        //查询视图
        BoolQueryBuilder diagramQuery = QueryBuilders.boolQuery();
        diagramQuery.must(QueryBuilders.termQuery("isOpen", 1));
        diagramQuery.must(QueryBuilders.termsQuery("dirId", categoryIdList));
        diagramQuery.must(QueryBuilders.termQuery("dataStatus", 1));
        diagramQuery.must(QueryBuilders.termQuery("status", 1));
        diagramQuery.must(QueryBuilders.termQuery("historyVersionFlag", 1));
        Page<ESDiagram> diagramPage = diagramApiClient.selectListByQuery(1,1, diagramQuery);
        if (!CollectionUtils.isEmpty(diagramPage.getData())) {
            return true;
        }
        //查询方案
        List<PlanDesignInstance> publishedPlan = planService.getPublishedPlan(categoryIdList, null);
        if (!CollectionUtils.isEmpty(publishedPlan)) {
            return true;
        }
        return false;
    }

    @Override
    public DiagramBo getPublishDiagramList(String like , Integer pageNum, Integer pageSize) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        List<ESSimpleDiagramDTO> esSimpleDiagramList = new ArrayList<>();
        EamDiagramQuery eamDiagramQuery = new EamDiagramQuery();
        // 根据条件查询视图库数据
        boolQueryBuilder.must(QueryBuilders.termQuery("status", Env.STATUS_VALID));
        boolQueryBuilder.must(QueryBuilders.termQuery("dataStatus",Env.DATA_STATUS_VALID));
        boolQueryBuilder.must(QueryBuilders.termQuery("historyVersionFlag",Env.MAJOR_VERSION));
        boolQueryBuilder.must(QueryBuilders.termQuery("isOpen", Env.OPEN));
        if (!com.binary.core.lang.StringUtils.isEmpty(like)) {
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("name.keyword","*"+like.trim()+"*"));
        }

        if (Objects.isNull(pageNum)) {
            pageNum = 1;
        }
        if (Objects.isNull(pageSize)) {
            pageSize = 500;
        }
        List<SortBuilder<?>> sorts = new ArrayList<>();
        sorts.add(SortBuilders.fieldSort("modifyTime").order(SortOrder.DESC));

        Page<ESDiagram> sortedPage = esDiagramDao.getSortListByQuery(pageNum, pageSize, boolQueryBuilder, sorts);
        List<ESDiagram> diagramData = sortedPage.getData();
        DiagramBo diagramBo = new DiagramBo();
        List<ESDiagram> data = new ArrayList<>();
        if(!org.springframework.util.CollectionUtils.isEmpty(diagramData)){
            List<Long> dirIdList = diagramData.stream().filter(item -> item.getDirId() != null && item.getDirId() != 0l).map(ESDiagram::getDirId).distinct().collect(Collectors.toList());
            List<EamCategory> categoryList = categorySvc.getByIds(dirIdList, LibType.DESIGN);
            Map<Long, EamCategory> categoryMap = categoryList.stream().collect(Collectors.toMap(EamCategory::getId, e -> e, (k1, k2) -> k2));
            for(ESDiagram diagram : diagramData){
                ESSimpleDiagramDTO diagramDTO = new ESSimpleDiagramDTO();
                String icon1 = diagram.getIcon1();
                if (icon1 != null && !icon1.startsWith(httpResourceUrl)) {
                    icon1 = httpResourceUrl + icon1;
                    diagram.setIcon1(icon1);
                }
                String diagramBgImg = diagram.getDiagramBgImg();
                if (diagramBgImg != null && !BinaryUtils.isEmpty(diagramBgImg.trim()) && !diagramBgImg.startsWith(httpResourceUrl)) {
                    diagramBgImg = httpResourceUrl + diagramBgImg;
                    diagram.setDiagramBgImg(diagramBgImg);
                }
                Long dirId = diagram.getDirId();
                if (dirId != null) {
                    if (dirId == 0L) {
                        diagram.setRelationLocation("企业级架构资产");
                    } else {
                        EamCategory diagramDir =categoryMap.get(dirId);
                        if (diagramDir != null && !com.binary.core.lang.StringUtils.isEmpty(diagramDir.getDirName())) {
                            diagram.setRelationLocation(diagramDir.getDirName());
                        }
                    }
                }
                if (!BinaryUtils.isEmpty(diagram.getReleaseDiagramId()) && diagram.getIsOpen() == 0) {
                    diagram.setReleaseStatus(1);
                }
                //TODO 精简处理
                ESDiagram esDiagram = new ESDiagram();
                esDiagram.setId(diagram.getId());
                esDiagram.setIcon1(diagram.getIcon1());
                esDiagram.setDiagramBgImg(diagram.getDiagramBgImg());
                esDiagram.setRelationLocation(diagram.getRelationLocation());
                esDiagram.setName(diagram.getName());
                data.add(esDiagram);
            }
        }
        diagramBo.setDiagramList(data);
        diagramBo.setPageSize(sortedPage.getPageSize());
        diagramBo.setPageNum(sortedPage.getPageNum());
        diagramBo.setTotalRows(sortedPage.getTotalRows());
        diagramBo.setTotalPages(sortedPage.getTotalPages());

        return diagramBo;
    }
}
